# -*- encoding: utf-8 -*-
"""
封装各项目接口调用基础方法
"""
import re
import json
from Common.log import MyLog
from src.ApiTest.ProjectConfig.Database.baseInfo_database import BaseInfoConfig, BaseInfoConfigSchema
from src.ApiTest.ProjectConfig.Database.header_database import HeaderConfig, HeaderConfigSchema
from src.ApiTest.ConfigurationData.Database.data_database import TestData, TestDataSchema
from src.ApiTest.Core.base_request import Request
from src.ApiTest.Core.sys_function import SysFunction
from functools import partial


class ApiRequest:
    def __init__(self):
        self.log = MyLog()

    @staticmethod
    def api_request(project_name, system_name, environment, api_data):
        """
        封装 request 请求方法
        :param project_name:项目名称，必填
        :param system_name: 系统名称，必填
        :param environment: 运行环境，必填
        :param api_data: 接口请求信息
        :return: 返回接口响应体信息
        """
        # 获取 base url 和公共请求头 header
        base_info_data = BaseInfoConfig.query.filter_by(systemName=system_name).first()
        if base_info_data:
            base_schema = BaseInfoConfigSchema()
            base_info = base_schema.dump(base_info_data)
            # base URL
            if environment == 'test':
                base_url = base_info['base_url_test']
            elif environment == 'develop':
                base_url = base_info['base_url_develop']
            else:
                base_url = base_info['base_url_release']
            # 判断baseUrl是否配置
            if not base_url:
                return {'data': KeyError(f'当前环境没有配置baseUrl信息，请检查系统配置是否配置正确'), 'ErrorCode': 200}
            # 公共请求头headers
            base_headers = json.loads(base_info['header'])
        else:
            return {'data': KeyError(f'当前环境没有配置系统基础信息，请检查系统配置是否配置正确'), 'ErrorCode': 200}

        # API请求信息
        method = api_data['method']
        path = api_data['path']
        url = base_url + path
        api_headers = api_data['headers']
        print(api_headers)
        pre_parameter = json.loads(api_data['pre_parameter'])

        # 重组前置参数
        pre_data = {}
        for pre_dic in pre_parameter:
            if pre_dic['parameterType']:
                pre_data[pre_dic['parameterName']] = pre_dic['parameterType']

        # 对请求头信息进行处理
        if api_headers:
            # 找到接口请求头中所有 ${...} 匹配项
            matches = re.findall(r'\$\{([^}]*)\}', api_headers)
            # 判断是否存在形参
            if matches:
                # 查询项目下所有的参数
                # TODO 后面需要将该查询放在运行用例之前
                # TODO 除了需要处理系统配置参数外，还需要处理接口返回参数
                datas = TestData.query.filter_by(projectName=project_name).all()
                test_datas = {}
                for i in datas:
                    test_schema = TestDataSchema()
                    test_data = test_schema.dump(i)
                    # 将单条信息添加到info中
                    test_datas[test_data['data_name']] = [test_data['data_key'], test_data['data_value'],
                                                          test_data['data_type']]
                # 循环替换所以的参数
                for parameter in matches:
                    if parameter in pre_data:
                        if pre_data[parameter] == '系统配置参数':
                            if parameter in test_datas:
                                if test_datas[parameter][2] == '1':
                                    # 使用自定义参数值
                                    replacement = test_datas[parameter][1]
                                    # 替换参数
                                    api_headers = api_headers.replace('${' + parameter + '}', replacement)
                                else:
                                    # 使用内置函数变量生成的值
                                    # 检查类对象中是否存在指定的函数
                                    if hasattr(SysFunction(), test_datas[parameter][0]) and callable(
                                            getattr(SysFunction(), test_datas[parameter][0])):
                                        # 调用函数并获取结果
                                        function = getattr(SysFunction(), test_datas[parameter][0])
                                        new_data = function()
                                        # 替换参数
                                        api_headers = api_headers.replace('${' + parameter + '}', new_data)
                                    else:
                                        return {'data': ValueError(f"Function '{test_datas[parameter][0]}' "
                                                                   f"not found in class ' {SysFunction()}'"),
                                                'ErrorCode': 500}
                            else:
                                return {'data': ValueError(f"没有找到headers中的配置参数 '{parameter}'"), 'ErrorCode': 500}
                        elif pre_data[parameter] == '接口返回参数':
                            print('此处替换接口返回参数')
                        else:
                            return {'data': ValueError(f"没有找到headers中的配置参数 '{parameter}'"), 'ErrorCode': 500}
                    else:
                        return {'data': KeyError(f"headers中的参数 '{parameter}' 未配置"), 'ErrorCode': 500}
            if base_headers:
                headers = dict(base_headers, **eval(api_headers))
            else:
                headers = eval(api_headers)
        else:
            headers = base_headers

        # 对请求体信息进行处理
        if api_data['body']:
            api_body = api_data['body']
            # 找到接口请求头中所有 ${...} 匹配项
            matches = re.findall(r'\$\{([^}]*)\}', api_body)
            # 判断是否存在形参
            if matches:
                # 查询项目下所有的参数
                # TODO 后面需要将该查询放在运行用例之前
                # TODO 除了需要处理系统配置参数外，还需要处理接口返回参数
                datas = TestData.query.filter_by(projectName=project_name).all()
                test_datas = {}
                for i in datas:
                    test_schema = TestDataSchema()
                    test_data = test_schema.dump(i)
                    # 将单条信息添加到info中
                    test_datas[test_data['data_name']] = [test_data['data_key'], test_data['data_value'],
                                                          test_data['data_type']]
                # 循环替换所以的参数
                for body_parameter in matches:
                    if body_parameter in pre_data:
                        if pre_data[body_parameter] == '系统配置参数':
                            if body_parameter in test_datas:
                                if test_datas[body_parameter][2] == '1':
                                    # 使用自定义参数值
                                    body_replacement = test_datas[body_parameter][1]
                                    # 替换参数
                                    api_body = api_body.replace('${' + body_parameter + '}', body_replacement)
                                else:
                                    # 使用内置函数变量生成的值
                                    # 检查类对象中是否存在指定的函数
                                    if hasattr(SysFunction(), test_datas[body_parameter][0]) and callable(
                                            getattr(SysFunction(), test_datas[body_parameter][0])):
                                        # 调用函数并获取结果
                                        function = getattr(SysFunction(), test_datas[body_parameter][0])
                                        new_data = function()
                                        # 替换参数
                                        api_body = api_body.replace('${' + body_parameter + '}', new_data)
                                    else:
                                        return {'data': ValueError(f"Function '{test_datas[body_parameter][0]}' "
                                                                   f"not found in class ' {SysFunction()}'"),
                                                'ErrorCode': 500}
                            else:
                                return {'data': ValueError(f"没有找到body中的配置参数 '{body_parameter}'"), 'ErrorCode': 500}
                        elif pre_data[body_parameter] == '接口返回参数':
                            print('此处替换接口返回参数')
                        else:
                            raise ValueError(f"没有找到body中的配置参数 '{body_parameter}'")
                    else:
                        return {'data': KeyError(f"body中的参数 '{body_parameter}' 未配置"), 'ErrorCode': 500}
            request_data = json.dumps(eval(api_body))
        else:
            request_data = api_data['body']

        files = ''
        params = ''

        response = Request().base_request(method, url, headers, body=request_data, files=files, params=params)

        return {'data': response.json(), 'ErrorCode': 200}
